package com.duguo.dynamicmvc.factory.stage;

import java.lang.reflect.Modifier;
import java.util.List;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

import com.duguo.dynamicmvc.factory.ControllerFactory;
import com.duguo.dynamicmvc.factory.WorkingModel;
import com.duguo.dynamicmvc.factory.processor.controller.ControllerProcessor;
import com.duguo.dynamicmvc.factory.utils.javassist.MethodUtils;

public class SetupFlagStage implements Stage {

    public void execute(ControllerFactory controllerFactory) throws Exception {
        WorkingModel workingModel = controllerFactory.getWorkingModel();
		ControllerProcessor controllerProcessor = controllerFactory.getControllerBuilder().getProcessorHolder().getControllerProcessor();
        Class controllerClass = workingModel.getControllerClass();
        
		if (!workingModel.isRootController()) {
            ControllerFactory parentFactory = controllerProcessor.getParentControllerFactory(workingModel);
            workingModel.setParentWorkModel(parentFactory.getWorkingModel());
        }
		setupMultiActionControllerFlag(workingModel, controllerClass);
        setupSingleActionControllerFlag(workingModel, controllerClass, controllerProcessor);
        setupDynamicControllerFlag(workingModel, controllerProcessor, controllerClass);
    }
    
    private void setupMultiActionControllerFlag(WorkingModel workingModel, Class controllerClass) throws Exception {
    	CtClass controllerAbstractCtClass = getControllerAbstractCtClass(controllerClass);
        
        CtMethod methodFromConcreateClass = MethodUtils.findMethod(controllerAbstractCtClass, "handleRequest");
        if (methodFromConcreateClass != null && !Modifier.isAbstract(methodFromConcreateClass.getModifiers())) {
        	workingModel.setMultiActionController(false);
        }
    }
    
    private void setupSingleActionControllerFlag(WorkingModel workingModel, Class controllerClass, ControllerProcessor controllerProcessor) throws Exception {
    	if(workingModel.isMultiActionController()) {
	    	CtClass controllerAbstractCtClass = getControllerAbstractCtClass(controllerClass);
	    	List<CtMethod> methodControllers=controllerProcessor.getControllerMethods(controllerAbstractCtClass);
	    	if(methodControllers.size()==1 && methodControllers.get(0).getName().equals("index")) {
	    		workingModel.setSingleActionController(true);
	        	workingModel.setMultiActionController(false);
	    	}
    	}
    }
    


    private void setupDynamicControllerFlag(WorkingModel workingModel, ControllerProcessor controllerProcessor, Class controllerClass) throws Exception {
    	if(workingModel.isMultiActionController() || workingModel.isSingleActionController()) {
	    	CtClass controllerAbstractCtClass = getControllerAbstractCtClass(controllerClass);
	        CtMethod dynamicControllerCtMethod = controllerProcessor.findDynamicMethod(controllerAbstractCtClass);
	        if (dynamicControllerCtMethod != null) {
	            workingModel.setDynamicController(true);
	        }
    	}
    }

	private CtClass getControllerAbstractCtClass(Class controllerClass) throws NotFoundException {
		CtClass controllerAbstractCtClass = ClassPool.getDefault().get(controllerClass.getName());
		return controllerAbstractCtClass;
	}

}
